package com.example.weixincommonlog.interceptor;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.example.mq.send.AmqpSender;
import com.example.weixincommonlog.annotation.WxLog;
import com.weixin.common.core.entity.SysLog;
import com.weixin.common.core.form.LoginUserDetails;
import com.weixin.common.core.utils.IpUtil;
import com.weixin.common.core.utils.SecurityUtil;
import com.weixin.common.core.utils.ServletUtil;
import com.weixin.common.core.utils.TokenUtil;
import com.weixin.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @version 1.0.0
 * @className: SysLogInterceptor
 * @description: 系统日志拦截器
 * @author: zhangjunfa
 * @date: 2023/7/5 15:54
 */
@Slf4j
public class SysLogInterceptor implements HandlerInterceptor {
    private final String DEFAULT_URL = "/login";
    private final RedisService redisService;
    private final AmqpSender amqpSender;

    public SysLogInterceptor(RedisService redisService, AmqpSender amqpSender) {
        this.redisService = redisService;
        this.amqpSender = amqpSender;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String token = SecurityUtil.getToken(request);
        Map<String, String> requestParams = ServletUtil.getRequestParams(request);
        String url = request.getRequestURI();
        String ip = IpUtil.getIpAddr(request);
        String address = IpUtil.getRealAddress();
        //扫描被 WxLog 标记的方法
        WxLog wxAnnotation = method.getAnnotation(WxLog.class);
        if (wxAnnotation != null) {
            SysLog sysLog = new SysLog();
            sysLog.setRequestUrl(url);
            sysLog.setTitle(wxAnnotation.title());
            sysLog.setBusinessType(wxAnnotation.type().ordinal());
            sysLog.setOperatorType(wxAnnotation.operator().ordinal());
            sysLog.setRequestIp(ip);
            sysLog.setRequestParam(requestParams.toString());
            sysLog.setRequestLocation(address);
            sysLog.setRequestMethod(request.getMethod());
            log.info("ip:{},获取到的归属地：{}", ip, address);
            //从redis中获取用户信息
            if (url.equals(DEFAULT_URL) && StringUtils.isEmpty(token)) {
                sysLog.setCreatedBy(requestParams.get("userName"));
            } else {
                LoginUserDetails loginUser = redisService.getCacheObject(TokenUtil.getRedisCacheKey(token));
                sysLog.setCreatedBy(loginUser.getUsername());
            }
            sysLog.setCreatedTime(DateUtil.date());
            log.info("系统操作日志收集：{}", JSONObject.toJSONString(sysLog));
            this.amqpSender.send(JSONObject.toJSONString(sysLog));
        }
        //必须返回true,否则会被拦截一切请求
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
